"""
文件名: main.py
描述: FastAPI应用主入口

本模块包含以下主要功能：
1. FastAPI应用初始化和配置
2. 中间件设置
3. 路由注册
4. 错误处理
5. 生命周期事件处理

依赖模块:
   - fastapi: Web框架
   - uvicorn: ASGI服务器
   - core: 核心配置模块
   - api: API路由模块

使用示例:
   >>> uvicorn src.main:app --host 127.0.0.1 --port 5656 --reload

注意事项:
   - 生产环境要配置安全中间件
   - 日志要记录请求和响应
   - 错误处理要用户友好
   - 启动时要初始化服务

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

import time
from contextlib import asynccontextmanager
from typing import Dict, Any

from fastapi import FastAPI, Request, Response, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPException

from src.core.config import get_settings
from src.core.logger import get_logger, log_api_access
from src.core.database import init_database, close_database, database_health_check
from src.core.redis import init_redis, close_redis, redis_health_check
from src.api import create_api_router
from src.utils.exceptions import YouTubeManagerException

# 获取配置和日志
settings = get_settings()
logger = get_logger(__name__)


@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    应用生命周期管理
    
    Args:
        app: FastAPI应用实例
    """
    # 启动时初始化
    logger.info("YouTube订阅管理器启动中...")
    
    try:
        # 初始化数据库
        await init_database()
        logger.info("数据库初始化完成")
        
        # 初始化Redis
        await init_redis()
        logger.info("Redis初始化完成")
        
        # 初始化YouTube服务
        from src.services.youtube_service import YouTubeService
        youtube_service = YouTubeService()
        await youtube_service.initialize()
        logger.info("YouTube服务初始化完成")
        
        # 初始化性能监控和缓存
        from src.utils.cache import cache_manager
        from src.utils.rate_limiter import rate_limiter, youtube_quota_manager
        from src.utils.performance import start_performance_monitoring
        
        await cache_manager.initialize()
        await rate_limiter.initialize()
        await youtube_quota_manager.initialize()
        await start_performance_monitoring()
        logger.info("性能优化组件初始化完成")
        
        logger.info(f"应用启动成功 - {settings.app_name} v{settings.app_version}")
        
    except Exception as e:
        logger.error(f"应用启动失败: {e}")
        raise
    
    yield
    
    # 关闭时清理
    logger.info("YouTube订阅管理器关闭中...")
    
    try:
        await close_redis()
        logger.info("Redis连接已关闭")
        
        await close_database()
        logger.info("数据库连接已关闭")
        
        logger.info("应用关闭完成")
        
    except Exception as e:
        logger.error(f"应用关闭时发生错误: {e}")


def create_application() -> FastAPI:
    """
    创建FastAPI应用实例
    
    Returns:
        FastAPI: 配置好的FastAPI应用
    """
    app = FastAPI(
        title=settings.app_name,
        version=settings.app_version,
        description="智能的YouTube订阅管理工具，帮助用户分类管理和高效浏览订阅内容",
        docs_url=settings.docs_url if settings.debug else None,
        redoc_url=settings.redoc_url if settings.debug else None,
        lifespan=lifespan,
    )
    
    # 配置CORS中间件
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"] if settings.debug else ["https://yourdomain.com"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    
    # 配置可信主机中间件（生产环境）
    if not settings.debug:
        app.add_middleware(
            TrustedHostMiddleware,
            allowed_hosts=["yourdomain.com", "*.yourdomain.com"]
        )
    
    # 添加请求日志中间件
    @app.middleware("http")
    async def log_requests(request: Request, call_next):
        """记录API请求日志"""
        start_time = time.time()
        
        # 获取客户端信息
        client_ip = request.client.host if request.client else "unknown"
        if "x-forwarded-for" in request.headers:
            client_ip = request.headers["x-forwarded-for"].split(",")[0].strip()
        elif "x-real-ip" in request.headers:
            client_ip = request.headers["x-real-ip"]
        
        user_agent = request.headers.get("user-agent", "unknown")
        
        # 处理请求
        response = await call_next(request)
        
        # 计算响应时间
        process_time = (time.time() - start_time) * 1000
        
        # 记录访问日志
        log_api_access(
            method=request.method,
            path=str(request.url.path),
            status_code=response.status_code,
            response_time=process_time,
            ip=client_ip,
            user_agent=user_agent,
        )
        
        # 添加响应头
        response.headers["X-Process-Time"] = str(process_time)
        
        return response
    
    # 注册API路由
    api_router = create_api_router()
    app.include_router(api_router, prefix=settings.api_v1_prefix)
    
    # 健康检查端点
    @app.get("/health", tags=["健康检查"])
    async def health_check():
        """应用健康检查"""
        try:
            # 检查数据库连接
            db_healthy = await database_health_check()
            
            # 检查Redis连接
            redis_healthy = await redis_health_check()
            
            # 总体健康状态
            healthy = db_healthy and redis_healthy
            
            status_code = status.HTTP_200_OK if healthy else status.HTTP_503_SERVICE_UNAVAILABLE
            
            return JSONResponse(
                status_code=status_code,
                content={
                    "status": "healthy" if healthy else "unhealthy",
                    "timestamp": time.time(),
                    "services": {
                        "database": "healthy" if db_healthy else "unhealthy",
                        "redis": "healthy" if redis_healthy else "unhealthy",
                    },
                    "version": settings.app_version,
                }
            )
        except Exception as e:
            logger.error(f"健康检查失败: {e}")
            return JSONResponse(
                status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
                content={
                    "status": "unhealthy",
                    "error": "Health check failed",
                    "timestamp": time.time(),
                }
            )
    
    # 根路径
    @app.get("/", tags=["根路径"])
    async def root():
        """应用根路径"""
        return {
            "name": settings.app_name,
            "version": settings.app_version,
            "description": "YouTube订阅管理器API",
            "docs_url": settings.docs_url,
            "health_check": "/health",
        }
    
    return app


def setup_exception_handlers(app: FastAPI) -> None:
    """
    设置异常处理器
    
    Args:
        app: FastAPI应用实例
    """
    
    @app.exception_handler(YouTubeManagerException)
    async def youtube_manager_exception_handler(request: Request, exc: YouTubeManagerException):
        """处理自定义业务异常"""
        logger.warning(f"业务异常: {exc}", path=str(request.url.path))
        return JSONResponse(
            status_code=status.HTTP_400_BAD_REQUEST,
            content=exc.to_dict()
        )
    
    @app.exception_handler(RequestValidationError)
    async def validation_exception_handler(request: Request, exc: RequestValidationError):
        """处理请求验证异常"""
        logger.warning(f"请求验证失败: {exc}", path=str(request.url.path))
        return JSONResponse(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            content={
                "error": True,
                "code": "VALIDATION_ERROR",
                "message": "请求参数验证失败",
                "details": exc.errors(),
            }
        )
    
    @app.exception_handler(StarletteHTTPException)
    async def http_exception_handler(request: Request, exc: StarletteHTTPException):
        """处理HTTP异常"""
        logger.warning(f"HTTP异常: {exc.status_code} - {exc.detail}", path=str(request.url.path))
        return JSONResponse(
            status_code=exc.status_code,
            content={
                "error": True,
                "code": f"HTTP_{exc.status_code}",
                "message": exc.detail,
            }
        )
    
    @app.exception_handler(Exception)
    async def general_exception_handler(request: Request, exc: Exception):
        """处理通用异常"""
        logger.error(f"未处理的异常: {exc}", path=str(request.url.path), exc_info=True)
        return JSONResponse(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            content={
                "error": True,
                "code": "INTERNAL_SERVER_ERROR", 
                "message": "服务器内部错误" if not settings.debug else str(exc),
            }
        )


# 创建应用实例
app = create_application()

# 设置异常处理器
setup_exception_handlers(app)

# 如果直接运行此文件
if __name__ == "__main__":
    import uvicorn
    
    uvicorn.run(
        "src.main:app",
        host=settings.host,
        port=settings.port,
        reload=settings.debug,
        log_level=settings.log_level.lower(),
    )